home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / system / linux_bo / netboot.zoo / bootp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-04  |  4.8 KB  |  206 lines

  1. /*
  2.  *     BOOTP
  3.  *     Bootp Routines
  4.  *
  5.  ****************************************************************************
  6.  *    Originally                                *
  7.  *      part of:                                                                *
  8.  *      TCP/IP kernel for NCSA Telnet                                               *
  9.  *      by Tim Krauskopf                                                        *
  10.  *                                                                              *
  11.  *      National Center for Supercomputing Applications                         *
  12.  *      152 Computing Applications Building                                     *
  13.  *      605 E. Springfield Ave.                                                 *
  14.  *      Champaign, IL  61820                                                    *
  15.  *                                                                              *
  16.  ****************************************************************************
  17.  *
  18.  * Modified Apr / May 1993 by Jamie Honan
  19.  */
  20.  
  21. #include "protocol.h"
  22. #include "bootinc.h"
  23. #include "bootp.h"
  24.  
  25. /*
  26.  *    Bootp routines : from the Clarkson 2.2 version of NCSA Telnet.
  27.  *    Thanks to Brad Clements for implementing this!
  28.  *
  29.  * bootp routines - These routines are based on the stanford/clarkson
  30.  * bootp code. Originally developed at Stanford University.
  31.  *
  32.  * Bootp is a UDP based protocol that determines the clients IP address and
  33.  * gateway information etc.
  34.  */
  35.  
  36. static struct bootp bootpacket;
  37. static u_long   bootp_xid;
  38.  
  39. /* sends a bootp broadcast packet */
  40. /* this routine does not do the initial setup of the bootp packet */
  41.  
  42. static int 
  43. sendbootp(void)
  44. {
  45.     return (netusend(broadip, broadaddr, IPPORT_BOOTPS, IPPORT_BOOTPC, (unsigned char *) &bootpacket, (int) sizeof(struct bootp)));
  46. }
  47.  
  48. /* initialize the bootp packet */
  49. static void 
  50. bootp_init(char *name)
  51. {
  52.     bootp_xid = n_ticks();               /* get a unique transaction ID */
  53.     memset((char *) &bootpacket, 0, sizeof(bootpacket));
  54.     bootpacket.bp_op = BOOTREQUEST;
  55.     bootpacket.bp_htype = 1;    /* hardware type 1 is ethernet. This
  56.                      * should be made more robust. */
  57.     bootpacket.bp_hlen = sizeof(nnmyaddr);
  58.     bootpacket.bp_xid = bootp_xid;
  59.     bootpacket.bp_secs = 1;
  60.     strncpy(bootpacket.bp_file, name, sizeof(bootpacket.bp_file) - 1);
  61.     /* boot file name */
  62.     memcpy(bootpacket.bp_chaddr, nnmyaddr, sizeof(nnmyaddr));
  63. }
  64.  
  65. /* parse an incoming bootp packet */
  66. static int 
  67. parse_bootpacket(struct bootp * bp)
  68. {
  69.     unsigned char  *c;
  70.  
  71.     memcpy(nnipnum, &bp->bp_yiaddr, 4);
  72.     memcpy(nnipserver, &bp->bp_siaddr, 4);
  73.     if (!memcmp(bp->bp_vend, VM_RFC1048, 4))
  74.     {
  75.         c = bp->bp_vend + 4;
  76.         while ((*c != 255) && ((c - bp->bp_vend) < 64))
  77.         {
  78.             switch (*c)
  79.             {
  80.             case 0:    /* nop pad */
  81.                 c++;
  82.                 break;
  83.  
  84.             case 1:    /* subnet mask */
  85.                 c += *(c + 1) + 2;
  86.                 break;
  87.  
  88.             case 2:    /* time offset */
  89.                 c += *(c + 1) + 2;
  90.                 break;
  91.  
  92.             case 3:    /* gateways     */
  93.                 c += *(c + 1) + 2;
  94.                 break;
  95.  
  96.             case 4:    /* time servers */
  97.             case 5:    /* IEN=116 name server */
  98.                 c += *(c + 1) + 2;
  99.                 break;
  100.  
  101.             case 6:    /* domain name server */
  102.                 c += *(c + 1) + 2;
  103.                 break;
  104.  
  105.             case 7:    /* log server */
  106.             case 8:    /* cookie server */
  107.             case 9:    /* lpr server */
  108.             case 10:    /* impress server */
  109.             case 11:    /* rlp server */
  110.                 c += *(c + 1) + 2;
  111.                 break;
  112.  
  113.             case 12:    /* client host name     */
  114.                 c += *(c + 1) + 2;
  115.                 break;
  116.  
  117.             case 255:
  118.                 break;
  119.  
  120.             default:
  121.                 c += *(c + 1) + 2;
  122.                 break;
  123.             }
  124.         }
  125.     }
  126.     return (0);
  127. }
  128.  
  129. /*
  130. *   main processing of bootp lookup request calls
  131. *        sendbootp to send a bootp request,
  132. *  sets up the udp listen port etc, handles retries
  133. */
  134.  
  135. int 
  136. bootp(char *name, int namelen)
  137. {
  138.     int             x,
  139.                     y,
  140.                     delay;
  141.     u_long          start_time;
  142.     struct bootp   *bp;
  143.     int             ulen;
  144.     int        mask;
  145.  
  146.     bootp_init(name);
  147.  
  148.     bp = (struct bootp *) (&udp_rxdata.data);
  149.     while ((ulen = udprecv(&udp_rxdata, IPPORT_BOOTPC)) != 0)
  150.     {
  151.         if (ulen < 0)
  152.             return -ulen;
  153.     }
  154.     for (x = 0, mask = 1; x < BOOTP_RETRIES; x++)
  155.     {
  156.         if (debug)
  157.         {
  158.             n_printf("Bootp attempt %d\n", x+ 1);
  159.         }
  160.         else
  161.             n_printf(".");
  162.         if ((y = sendbootp()) != 0)
  163.         {    /* do some error processing */
  164.             return (y);
  165.         }
  166.  
  167.         start_time = n_secs();
  168.         delay = random(mask) + 1;
  169.         do
  170.         {
  171.             if (monitor_check() > 1)
  172.                 return 2000;
  173.             ulen = udprecv(&udp_rxdata, IPPORT_BOOTPC);
  174.             if (ulen)
  175.             {
  176.                 if (ulen < 0)
  177.                     return -ulen;
  178.                 delay = 0;
  179.                 break;
  180.             }
  181.         }
  182.         while ((n_secs() - start_time) < (long) delay);
  183.         /* This implements the mask shifting recommended in RFC 1048 */
  184.         if (mask < 127)
  185.             mask =  (mask << 1) | 1;
  186.         if (delay)
  187.             continue;    /* time ran out and got nothing */
  188.         if (((bp->bp_xid) == bootp_xid) && 
  189.             ((bp->bp_op) == BOOTREPLY) &&
  190.             (!memcmp(bp->bp_chaddr, nnmyaddr, sizeof(nnmyaddr))))
  191.             break;    /* got a valid reply */
  192.     }
  193.     if (x == BOOTP_RETRIES)
  194.     {    /* do some error processing */
  195.         /* no response error number */
  196.         return (1000);
  197.     }
  198.     if (parse_bootpacket(bp))
  199.         return (1001);
  200.     strncpy(name, bp->bp_file, namelen - 1);
  201.     name[namelen - 1] = '\0';
  202.     memcpy(nnserveraddr, udp_rxdata.d.me, DADDLEN);
  203.     return (0);
  204. }
  205.  
  206.